import { createHmac, privateEncrypt, publicDecrypt, randomBytes } from 'crypto';
import { readFileSync, existsSync, writeFileSync } from 'fs'

const BLOCKS_PATH = './blocks'
const HEADS_PATH = `${BLOCKS_PATH}/head`
const LAST_NODE_PATH = `${BLOCKS_PATH}/lastNode`
const SIGN_LENGTH = 25
const PUB_KEY = readFileSync('./pub.key').toString()
const PRI_KEY = readFileSync('./pri.key').toString()

const getHash = secret => createHmac('sha256', secret).update('MinarBlockChain').digest('hex')
const encrypt = buffer => privateEncrypt(PRI_KEY, buffer)
const decrypt = buffer => publicDecrypt(PUB_KEY, buffer)

if (!existsSync(HEADS_PATH)) {
  writeFileSync(HEADS_PATH, 'I am the head of Minar Block Chain!')
}

export const addNode = secret => {
  let lastNode = existsSync(LAST_NODE_PATH) && readFileSync(LAST_NODE_PATH).toString()
  if (!lastNode || !existsSync(`${BLOCKS_PATH}/${lastNode}`)) {
    lastNode = 'head'
  }
  let lastNodeContent = readFileSync(`${BLOCKS_PATH}/${lastNode}`)
  let lastHash = getHash(lastNodeContent)
  if (!(secret instanceof Buffer)) {
    secret = Buffer.from(JSON.stringify(secret))
  }
  secret = encrypt(secret)
  const content = Buffer.concat([randomBytes(SIGN_LENGTH), secret])
  writeFileSync(`${BLOCKS_PATH}/${lastHash}`, content)
  writeFileSync(LAST_NODE_PATH, lastHash)
}

export const listNodes = () => {
  for (let hash = getHash(readFileSync(HEADS_PATH)); existsSync(`${BLOCKS_PATH}/${hash}`);) {
    const content = readFileSync(`${BLOCKS_PATH}/${hash}`)
    hash = getHash(content)
    console.log(decrypt(content.slice(SIGN_LENGTH)).toString())
  }
}